//! 线程创建和管理示例
//!展示如何在Rust中创建和管理线程
//!
//! ## 概念说明
//!在大多数现代操作系统中，执行的程序代码运行在进程（process）中，操作系统会同时管理多个进程。
//!在程序内部，也可以拥有多个同时运行的独立部分，这些独立部分被称为线程（thread）。
//!
//!将计算分割到多个线程中可以提高程序的性能，但也增加了程序的复杂性。
//!Rust试图通过所有权机制减少使用线程的负面影响，但程序仍然需要考虑以下问题：
//!
//!1. 竞争状态（Race conditions）：多个线程以不一致的顺序访问数据
//!2. 死锁（Deadlocks）：两个线程相互等待对方释放资源，导致程序阻塞
//!3. 只会发生在特定情况下的难以重现和修复的bug
//!
//! ## 线程相关知识点
//!| 知识点 | 说明 |
//!|--------|------|
//!| thread::spawn | 创建新线程执行代码 |
//!| JoinHandle | 等待线程执行完成 |
//!| move闭包 | 将所有权转移到线程中 |
//!| 线程间通信 | 线程之间安全地共享数据 |

use std::thread;
use std::time::Duration;

/// 创建一个简单的线程
///
/// 使用`thread::spawn`创建一个新的线程来执行闭包中的代码。
/// 当主线程结束时，新创建的线程也会停止，而不管其是否执行完成。
pub fn create_thread() {
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }

    handle.join().unwrap();
}

/// 使用move关键字将所有权转移到线程中
///
/// 当在线程中使用所属值时，需要使用`move`关键字将这些值的所有权从一个线程转移到另一个线程。
/// `move`闭包经常与`thread::spawn`一起使用，因为它允许在新线程中使用来自父线程的数据。
pub fn move_closure() {
    let v = vec![1, 2, 3];

    let handle = thread::spawn(move || {
        println!("Here's a vector: {:?}", v);
    });

    handle.join().unwrap();
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_thread_creation() {
        // 注意：这个测试不会验证输出，只是确保代码能正常运行
        create_thread();
    }

    #[test]
    fn test_move_closure() {
        move_closure();
    }
}
